import logging
import os
from traceback import format_exception

# pip install better_exceptions

from sam import default_console_log_file_path, default_error_log_file_path, default_error_dir_file_path, \
    default_console_dir_file_path, default_io_log_dir_path, default_chrome_dir_file_path, default_chrome_log_file_path, \
    default_io_log_file_path

default_formatter = "'%(asctime)s - %(name)s - %(levelname)s - %(message)s'"

default_date_fmt = "%Y-%m-%d %H:%M:%S"

_logger_level_dict = {
    "debug": logging.DEBUG,
    "info": logging.INFO,
    "warning": logging.WARNING,
    "critical": logging.CRITICAL,
    "error": logging.ERROR
}


class LoggerUtil(object):
    def __init__(self, name: str = "temp", level: str = None):
        super().__init__()
        self.name = name
        # 创建一个logger
        self.logger = logging.getLogger(self.name)
        self.level = _logger_level_dict.get(level, logging.INFO)
        # logger的总开关，只有大于Debug的日志才能被logger对象处理
        self.logger.setLevel(self.level)
        # 加了一步 判断文件夹是否存在
        if not os.path.exists(default_io_log_dir_path):
            os.makedirs(default_io_log_dir_path)
        # 创建一个handler，用于写入日志文件
        file_handler = logging.FileHandler(default_io_log_file_path, mode='a', encoding="utf-8")
        file_handler.setLevel(logging.ERROR)  # 输出到file的log等级的开关
        # 创建该handler的formatter
        file_handler.setFormatter(
            logging.Formatter(
                fmt=default_formatter,
                datefmt=default_date_fmt)
        )
        # 添加handler到logger中
        self.logger.addHandler(file_handler)

        # 第三步，创建一个handler，用于输出到控制台
        console_handler = logging.StreamHandler()
        # 输出到控制台的log等级的开关
        console_handler.setLevel(logging.INFO)
        # 创建该handler的formatter
        console_handler.setFormatter(
            logging.Formatter(
                # fmt='%(asctime)s - %(levelname)s: %(message)s',
                fmt=default_formatter,
                datefmt=default_date_fmt)
        )
        self.logger.addHandler(console_handler)


def get_info_logger():
    default_logger = logging.getLogger("default")
    default_logger.setLevel(logging.INFO)  # logger的总开关，只有大于Debug的日志才能被logger对象处理

    # 加了一步 判断文件夹是否存在
    if not os.path.exists(default_console_dir_file_path):
        os.makedirs(default_console_dir_file_path)
    # 第二步，创建一个handler，用于写入日志文件
    file_handler = logging.FileHandler(default_console_log_file_path, mode='w', encoding="utf-8")
    file_handler.setLevel(logging.ERROR)  # 输出到file的log等级的开关
    # 创建该handler的formatter
    file_handler.setFormatter(
        logging.Formatter(
            fmt=default_formatter,
            datefmt=default_date_fmt)
    )
    # 添加handler到logger中
    default_logger.addHandler(file_handler)

    # 第三步，创建一个handler，用于输出到控制台
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.INFO)  # 输出到控制台的log等级的开关
    # 创建该handler的formatter
    console_handler.setFormatter(
        logging.Formatter(
            # fmt='%(asctime)s - %(levelname)s: %(message)s',
            fmt=default_formatter,
            datefmt=default_date_fmt)
    )
    default_logger.addHandler(console_handler)
    return default_logger


def get_error_logger():
    error_logger = logging.getLogger("error")
    error_logger.setLevel(logging.ERROR)  # logger的总开关，只有大于Debug的日志才能被logger对象处理

    # 加了一步 判断文件夹是否存在
    if not os.path.exists(default_error_dir_file_path):
        os.makedirs(default_error_dir_file_path)
    # 第二步，创建一个handler，用于写入日志文件
    file_handler = logging.FileHandler(default_error_log_file_path, mode='w', encoding="utf-8")
    file_handler.setLevel(logging.ERROR)  # 输出到file的log等级的开关
    # 创建该handler的formatter
    file_handler.setFormatter(
        logging.Formatter(
            fmt=default_formatter,
            datefmt=default_date_fmt)
    )
    # 添加handler到logger中
    error_logger.addHandler(file_handler)

    # 第三步，创建一个handler，用于输出到控制台
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.ERROR)  # 输出到控制台的log等级的开关
    # 创建该handler的formatter
    console_handler.setFormatter(
        logging.Formatter(
            # fmt='%(asctime)s - %(levelname)s: %(message)s',
            fmt=default_formatter,
            datefmt=default_date_fmt)
    )
    error_logger.addHandler(console_handler)
    return error_logger


def get_chrome_logger():
    chrome_logger = logging.getLogger("chrome")
    chrome_logger.setLevel(logging.ERROR)  # logger的总开关，只有大于Debug的日志才能被logger对象处理

    # 加了一步 判断文件夹是否存在
    if not os.path.exists(default_chrome_dir_file_path):
        os.makedirs(default_chrome_dir_file_path)
    # 第二步，创建一个handler，用于写入日志文件
    file_handler = logging.FileHandler(default_chrome_log_file_path, mode='a', encoding="utf-8")
    file_handler.setLevel(logging.ERROR)  # 输出到file的log等级的开关
    # 创建该handler的formatter
    file_handler.setFormatter(
        logging.Formatter(
            fmt=default_formatter,
            datefmt=default_date_fmt)
    )
    # 添加handler到logger中
    chrome_logger.addHandler(file_handler)

    # 第三步，创建一个handler，用于输出到控制台
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.INFO)  # 输出到控制台的log等级的开关

    # 创建该handler的formatter
    console_handler.setFormatter(
        logging.Formatter(
            # fmt='%(asctime)s - %(levelname)s: %(message)s',
            fmt=default_formatter,
            datefmt=default_date_fmt)
    )
    chrome_logger.addHandler(console_handler)
    return chrome_logger


def get_debug_logger(name: str, mode: str = "ch", level: str = "DEBUG", filename: str = None):
    # 返回一个looger，当调用exception方法时，将显示报错参数的详情
    # fh为写入文件模式，filename是日志模式的文件名或文件路径加文件名
    # ch为控制台模式，即打印在控制台，不写入文件
    logger = logging.getLogger(name)
    logger.propagate = False
    logger.handlers.clear()
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    formatter.formatException = lambda exc_info: format_exception(*exc_info)
    if mode == "fh":
        handler = logging.FileHandler(filename or f"{name or 'temp'}.log")
    elif mode == "ch":
        handler = logging.StreamHandler()
    else:
        raise ValueError("Mode模式错误，应为'ch'[控制台输出模式] 或 'fh'[日志输出模式]")
    handler.setFormatter(formatter)
    logger.addHandler(handler)
    logger.setLevel(level)
    return logger
